<?php
/**
 * 
 * +------------------------------------------------------------+
 * @category Upload 
 * +------------------------------------------------------------+
 * 文件上传扩展类库
 * +------------------------------------------------------------+
 *
 * @author anzai <236049524@qq.com>
 * @copyright http://www.judianyun.com 2013
 * @version 1.0
 *
 * Modified at : 2013-2-25 16:22:08
 *
 */
class Upload extends Base {
	const FILEERR_SIZE = '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值';
	const FILEERR_HTML_SIZE = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值';
	const FILEERR_PARTEN = '文件只有部分被上传';
	const FILEERR_EMPTY = '没有文件被上传';
	const FILEERR_FOUND = '找不到临时文件夹';
	const FILEERR_WRITE = '文件写入失败';
	const FILEERR_DEFAULT = '文件上传发生未知错误';
	
	//文件重名是否进行覆盖，默认否
	public $cover = false;
	
	//允许上传文件名后缀，可为一个数组，或字符串（多个用英文逗号隔开）；为空或“*”表示不限制
	public $ext = '*';
	
	///上传文件中出现的错误信息
	private $_error = null;
	
	//是否重新命名文件，true重新命名，false使用原文件名
	public $rename = true;
	
	///存储路径
	private $_savepath = '';
	
	///允许上传文件大小的最大限制，-1表示不限制
	private $_size = -1;
	
	//允许上传文件MIME类型，可为一个数组，或字符串（多个用逗号隔开）；为空或“*”表示不限制
	public $type = '';
	
	///要上传文件的相关信息
	private $_uploads = array();
	
	/**
	 * @param string $savePath	上传文件存储路径
	 * @param string $ext		允许上传后缀名 
	 * @param int $size 		大小限制
	 * @param string $type		文件类型
	 *
	 */
	public function __construct($savePath, $ext=null, $size=null, $type=null){
		$this->Upload($savePath,$ext,$size,$type);
	}
	
	public function Upload($savePath,$ext=null,$size=null,$type=null){
		$this->_savepath = $savePath;
		
		if ($ext && $ext!='*'){
			$ext = is_array($ext) ? $ext : explode(',',$ext);
			$this->ext = array_map('strtolower',$ext);
		}

		if (!empty($type) && $type!='*'){
			$type = is_array($type) ? $type : explode(',',$type);
			$this->type = array_map('strtolower',$type);
		}
		
		$this->_size = $size!==null ? $size : -1;
		$this->_init();
	}
	
	private function _check($file){
		$err = null;
		$error = $this->_error($file['error']);
		if ($error){
			$err = $file['name'].'：'.$error;
		}elseif (!$this->_checkExt($this->_getExt($file['name']))){
			$err = $file['name'].'：文件名后缀不允许被上传';
		}elseif (!$this->_checkType($file['type'])){
			$err = $file['name'].'：文件类型不允许被上传';
		}elseif (!$this->_checkSize($file['size']))
			$err = $file['name'].'：文件大小超过限制';
		elseif (!is_uploaded_file($file['tmp_name'])){
			$err = $file['name'].'：非法上传';
		}
		return $err;
	}
	
	///检查文件名后缀是否合法
	private function _checkExt($ext){
		if (empty($this->ext) || $this->ext=='*') return true;
		return in_array(strtolower($ext),$this->ext);
	}
	
	///检查文件大小是否超过限制
	private function _checkSize($size){
		if ($this->_size==-1) return true;
		return $size <= $this->_size;
	}
	
	///检查文件MIME类型是否合法
	private function _checkType($type){
		if (empty($this->type) || $this->type=='*') return true;
		return in_array($type,$this->type);
	}
	
	private function _error($errno){
		if ($errno==0) return ;
		if ($errno>0 && $errno<=7)
			return $this->_msgs[$errno];
		else
			return $this->_msgs['unkonw'];
	}
	
	//获取错误信息
	public function getError(){
		return $this->_error;
	}
	
	///获取文件后缀
	private function _getExt($filename)
    {
        $pathinfo = pathinfo($filename);
        return $pathinfo['extension'];
    }
    
	///上传文件初始化
	private function _init(){
		if(count($_FILES) <= 0) return;
		$i = 0;
		$files = array();
		foreach ($_FILES as $file){
			if ($file['name']){
				$error = $this->_check($file);
				if ($error === null){
					$ext = $this->_getExt($file['name']);
					$savename = ($this->rename ? date('YmdHis') . $i . '@@@' : '') . time() . '.' . $ext;
					$files[] = array(
						'name' => $file['name'],				//原文件名
						'savename' => $savename,				//存储文件名
						'ext' => strtolower($ext),  			//文件后缀
						'tmpfile' => $file['tmp_name'], 		//临时文件路径
						'size' => $file['size'],        		//文件大小
						'type' => strtolower($file['type'])     //文件的MIME类型
					);
					$i++;
				}else{
					$this->_error[] = $error;
				}
			}
		}
		
		if (count($files) > 0){
			$this->_uploads = $files;
		}
	}
	
	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name save
	 * +------------------------------------------------------------+
	 * 上传保存文件
	 * +------------------------------------------------------------+
	 *
	 * @author anzai <236049524@qq.com>
	 * @version 1.0
	 * 
	 * @return 返回上传完后文件信息，单个文件时自动转换为一维数组
	 *
	 */
	public function save($savename = false){
		if (empty($this->_uploads)){
				if(!$this->_error){
					$this->_error[] = $this->_error(4);
				}
			return false;
		}
		$savepath = $this->_savepath;
		//不是目录则自动创建目录
		if (!is_dir($savepath)){
			if(!is_dir(base64_decode($savepath)))
				mkdir($savepath, 0755, true);
			else
				$savepath = base64_decode($savepath);
		}
		if (!is_writeable($savepath)){//检查目录是否可写
			$this->_error[] = '上传目录“'.$savepath.'”不可写';
			return false;
		}
		
		$count = count($this->_uploads);
		foreach ($this->_uploads as $file){
			$filename = $savepath.'/'.($savename ? $savename : $file['savename']);
			if ($this->cover==false){
				if(file_exists($filename)){
					$this->_error[] = $file['name'].'：文件已经存在';
					continue;
				}
			}
			
			if (!move_uploaded_file($file['tmpfile'], auto_charset($filename, 'utf-8', 'gbk'))){
				$this->_error[] = $file['name'].'：文件上传保存出现异常';
				continue;
			}

			$save[] = array(
				'file' => $file['savename'],
				'name' => $file['name'],
				'ext' => $file['ext'],
				'size' => $file['size']
			);
			if($count) sleep(1);
		}
		
		return count($save)==1 ? $save[0] : $save;
	}
}

?>